In the latter half of the twentieth century, there began a phenomenon known as the information revolution. While the information revolution is a historical development broader in scope than any one event or machine, no single device has come to represent the information revolution more than the digital electronic computer. The development of computer systems has surely been a revolution. Each year, computer systems grow faster, store more data, and provide more applications to their users.
A modern computer system typically comprises one or more central processing units (CPU) and supporting hardware necessary to store, retrieve and transfer information, such as communication buses and memory. It also includes hardware necessary to communicate with the outside world, such as input/output controllers or storage controllers, and devices attached thereto such as keyboards, monitors, tape drives, disk drives, communication lines coupled to a network, etc. The CPU or CPUs are the heart of the system. They execute the instructions which comprise a computer program and directs the operation of the other system components.
From the standpoint of the computer's hardware, most systems operate in fundamentally the same manner. Processors are capable of performing a limited set of very simple operations, such as arithmetic, logical comparisons, and movement of data from one location to another. But each operation is performed very quickly. Sophisticated software at multiple levels directs a computer to perform massive numbers of these simple operations, enabling the computer to perform complex tasks. What is perceived by the user as a new or improved capability of a computer system is made possible by performing essentially the same set of very simple operations, but using software having enhanced function, along with faster hardware.
In the very early history of the digital computer, computer programs which instructed the computer to perform some task were written in a form directly executable by the computer's processor. Such programs were very difficult for a human to write, understand and maintain, even when performing relatively simple tasks. As the number and complexity of such programs grew, this method became clearly unworkable. As a result, alternate forms of creating and executing computer software were developed.
Two developments in particular have been the use of a software hierarchy of multiple levels, and the use of high-level languages, particularly for user application programs. A software hierarchy models different levels of software according to the closeness to the actual hardware. At a low level, an operating system kernel typically performs such functions as the management of memory pages, management of multiple processor tasks, I/O and storage device interfaces, interrupt handling, and so forth. At a next level, operating system extensions and utilities might provide callable functions to user applications for application run time support, database management, storage allocation, program compilation, and so forth. At a still higher level, user applications perform work defined by a user, calling lower level routines as necessary. It will be understood that the concept of software hierarchy is very general, and the number of levels and division of function varies considerably from one computer system to another.
High-level languages vary in their characteristics, but all such languages are intended to make it easier for a human to write a program to perform some task. Typically, high-level languages represent instructions, fixed values, variables, and other constructs in a manner readily understandable to the human programmer rather than the computer. Such programs are not directly executable by the computer's processor. In order to run on the computer, the programs must first be transformed into a form that the processor can execute.
Transforming a high-level language program into executable form requires that the human-readable program form (source code) be converted to a processor-executable form (object code) in a compilation process. For very simple programs, the entire program is potentially compilable as a single unit. However, as programs have grown in complexity, and frequently call or invoke functions and procedures which are parts of other programs, it is often impractical to compile the program as a single unit. In a typical case, individual modules or parts of a program are separately compiled, and a further process, sometimes referred to herein as a build process, gathers the different parts and places references in each part to other parts as required, so that the parts may execute together as a single program.
As programs have grown in sophistication, it is known to employ program libraries of commonly used procedures. A program library is not intended to function as a stand-alone program, but is instead a collection of executable procedures or functions which may be used by other programs. Often, a program library has some common theme to the procedures contained therein for supporting applications of a certain family, such as an accounting library, a database library, a graphics library, and so forth. It is usually intended that such libraries be incorporated into many different applications by linking or binding to the application program, although it is not necessarily true that each application program will use all of the procedures in the library. The program library may contain many separately compiled individual modules.
Code modules and program libraries undergo frequent updates, which are not necessarily synchronized. When a large program is to be built from many separately compilable modules, a build tool typically verifies that the object module components are current. Conventionally, this is done by comparing timestamps of the various component parts with those of sub-components or source modules.
In the case of a program included by a referential technique, such as a program library, which is typically a collection of separately compiled modules, a conventional build process will compare the timestamp of the referenced program with that of the program which refers to it (is linked or bound to it). If the timestamp of the current referenced program is later, it is assumed that the program which refers to it is no longer current and must be re-built.
However, in many cases, the changes to a program library or other such referenced program would not necessarily require rebuilding all the programs which use it. For example, a program library may have been rebuilt (has a later date/timestamp) only because some new procedure was added, and the original procedures remain untouched. In these cases, it is possible for the program library to support multiple different versions for binding purposes, one of which corresponds to the most current build, while others are at a back level.
Thus, although not necessarily recognized, a certain amount of unnecessary rebuilding may occur when a build utility uses timestamps to determine which objects must be rebuilt, particularly where a build utility determines that a program must be rebuilt if any program library it is bound to has a later date/timestamp. An unrecognized need exists for a more intelligent method of determining whether to rebuild a program.